import tkinter as tk
import traceback
from tkinter import ttk, filedialog, messagebox, simpledialog, Listbox, Toplevel
from tkinter.scrolledtext import ScrolledText
import pandas as pd
import pyautogui
import time
import os
from PIL import Image
import sys
import openpyxl


class AutomationApp:
    def __init__(self, root):
        self.root = root
        self.root.title("自动化操作工具")
        self.root.geometry("1000x700")

        # 初始化数据
        self.data = []
        self.operations = []
        self.product_paths = {
            "AnyUkit": "D:\\AnyUkit\\anyukit.exe",
            "OtherApp": "C:\\Program Files\\OtherApp\\app.exe"
        }

        # 创建UI
        self.create_widgets()
        self.create_preset_operations()

    def create_preset_operations(self):
        # 预设操作及其详细描述
        self.preset_operations = {
            "打开软件": {
                "type": "open_app",
                "description": "根据产品名打开对应软件",
                "details": "需要配置程序路径"
            },
            "切换多语言": {
                "type": "change_language",
                "description": "切换到指定的语言版本",
                "details": "使用鼠标操作切换语言"
            },
            "截图": {
                "type": "screenshot",
                "description": "截取程序窗口并保存为文件名",
                "details": "截图区域: 448x206 到 1475x870"
            }
        }

    def create_widgets(self):
        # 创建框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 顶部按钮
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=5)

        import_btn = ttk.Button(button_frame, text="导入表格", command=self.import_data)
        import_btn.pack(side=tk.LEFT, padx=5)

        run_btn = ttk.Button(button_frame, text="执行操作", command=self.run_operations)
        run_btn.pack(side=tk.LEFT, padx=5)

        # 配置按钮
        config_btn = ttk.Button(button_frame, text="配置路径", command=self.configure_paths)
        config_btn.pack(side=tk.LEFT, padx=5)

        # 数据表格区域
        data_frame = ttk.LabelFrame(main_frame, text="导入的数据")
        data_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        # 创建表格
        columns = ("文件名", "产品名", "语言版本")
        self.table = ttk.Treeview(data_frame, columns=columns, show="headings")

        for col in columns:
            self.table.heading(col, text=col)
            self.table.column(col, width=100, anchor="w")

        # 添加垂直滚动条
        scrollbar_y = ttk.Scrollbar(data_frame, orient="vertical", command=self.table.yview)
        self.table.configure(yscrollcommand=scrollbar_y.set)

        # 添加水平滚动条
        scrollbar_x = ttk.Scrollbar(data_frame, orient="horizontal", command=self.table.xview)
        self.table.configure(xscrollcommand=scrollbar_x.set)

        # 布局
        self.table.pack(side="top", fill="both", expand=True)
        scrollbar_y.pack(side="right", fill="y")
        scrollbar_x.pack(side="bottom", fill="x")

        # 操作序列区域
        operations_frame = ttk.LabelFrame(main_frame, text="操作序列")
        operations_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        # 操作列表
        self.operations_list = Listbox(operations_frame, height=8)
        self.operations_list.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)

        # 操作按钮
        op_btn_frame = ttk.Frame(operations_frame)
        op_btn_frame.pack(fill=tk.X, pady=5)

        add_btn = ttk.Button(op_btn_frame, text="添加操作", command=self.add_operation)
        add_btn.pack(side=tk.LEFT, padx=5)

        up_btn = ttk.Button(op_btn_frame, text="上移", command=self.move_operation_up)
        up_btn.pack(side=tk.LEFT, padx=5)

        down_btn = ttk.Button(op_btn_frame, text="下移", command=self.move_operation_down)
        down_btn.pack(side=tk.LEFT, padx=5)

        remove_btn = ttk.Button(op_btn_frame, text="移除", command=self.remove_operation)
        remove_btn.pack(side=tk.LEFT, padx=5)

        # 状态栏
        self.status_var = tk.StringVar()
        self.status_var.set("就绪")
        status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    def import_data(self):
        file_path = filedialog.askopenfilename(
            filetypes=[("Excel文件", "*.xlsx *.xls"), ("CSV文件", "*.csv"), ("所有文件", "*.*")]
        )

        if not file_path:
            return

        try:
            # 清空现有数据
            self.data = []
            for item in self.table.get_children():
                self.table.delete(item)

            # 读取文件
            if file_path.endswith('.csv'):
                df = pd.read_csv(file_path)
            else:
                # 使用openpyxl引擎确保能读取所有Excel格式
                df = pd.read_excel(file_path, engine='openpyxl')

            # 查找包含.png文件名的列
            png_col = None
            for col in df.columns:
                # 检查列中是否包含.png字符串
                if any(df[col].astype(str).str.contains(r'\.png', case=False, na=False)):
                    png_col = col
                    break

            if png_col is None:
                messagebox.showerror("导入错误", "未找到包含.png文件名的列")
                return

            # 处理数据
            imported_count = 0
            for _, row in df.iterrows():
                filename = str(row[png_col]).strip()

                # 跳过非.png结尾的行
                if not filename.lower().endswith('.png'):
                    continue

                # 解析文件名 - 格式: AnyUkit-it-newuser.png
                parts = filename.split('-')
                if len(parts) < 2:
                    # 尝试其他分隔符
                    parts = filename.split('_')
                    if len(parts) < 2:
                        continue

                # 提取产品名和语言
                product = parts[0]
                lang = parts[1]

                # 添加到数据列表
                self.data.append({
                    "filename": filename,
                    "product": product,
                    "language": lang
                })

                # 添加到表格
                self.table.insert("", "end", values=(filename, product, lang))
                imported_count += 1

            if imported_count > 0:
                self.status_var.set(f"成功导入 {imported_count} 条数据")
            else:
                messagebox.showinfo("导入结果", "未找到符合格式的.png文件名")

        except Exception as e:
            messagebox.showerror("导入错误", f"导入数据时出错: {str(e)}\n{traceback.format_exc()}")

    def add_operation(self):
        # 创建选择操作对话框
        dialog = Toplevel(self.root)
        dialog.title("添加操作")
        dialog.geometry("400x300")
        dialog.transient(self.root)
        dialog.grab_set()

        # 对话框内容
        content_frame = ttk.Frame(dialog)
        content_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 操作选择标签
        ttk.Label(content_frame, text="请选择要添加的操作:").pack(pady=5)

        # 创建下拉选择框
        op_var = tk.StringVar()
        op_combobox = ttk.Combobox(content_frame, textvariable=op_var, state="readonly")
        op_combobox['values'] = list(self.preset_operations.keys())
        op_combobox.current(0)
        op_combobox.pack(pady=5, fill=tk.X)

        # 操作描述区域
        ttk.Label(content_frame, text="操作描述:").pack(pady=5)

        desc_text = ScrolledText(content_frame, height=5, wrap=tk.WORD)
        desc_text.pack(fill=tk.BOTH, expand=True, pady=5)

        # 更新描述信息
        def update_description(event=None):
            op_name = op_var.get()
            if op_name in self.preset_operations:
                op_info = self.preset_operations[op_name]
                desc_text.delete(1.0, tk.END)
                desc_text.insert(tk.END, f"描述: {op_info['description']}\n\n")
                desc_text.insert(tk.END, f"详情: {op_info['details']}")

        op_combobox.bind("<<ComboboxSelected>>", update_description)
        update_description()  # 初始化显示

        # 确认按钮
        def confirm():
            op_name = op_var.get()
            if op_name:
                # 添加到操作序列
                op_info = self.preset_operations[op_name]
                self.operations.append({
                    "name": op_name,
                    "type": op_info["type"],
                    "description": op_info["description"]
                })
                self.update_operations_list()
            dialog.destroy()

        btn_frame = ttk.Frame(dialog)
        btn_frame.pack(fill=tk.X, padx=10, pady=10)

        ttk.Button(btn_frame, text="确定", command=confirm).pack(side=tk.RIGHT, padx=5)
        ttk.Button(btn_frame, text="取消", command=dialog.destroy).pack(side=tk.RIGHT, padx=5)

    def update_operations_list(self):
        self.operations_list.delete(0, tk.END)
        for op in self.operations:
            self.operations_list.insert(tk.END, f"{op['name']} - {op['description']}")

    def move_operation_up(self):
        selected = self.operations_list.curselection()
        if not selected:
            return
        index = selected[0]
        if index > 0:
            self.operations[index], self.operations[index - 1] = self.operations[index - 1], self.operations[index]
            self.update_operations_list()
            self.operations_list.select_set(index - 1)

    def move_operation_down(self):
        selected = self.operations_list.curselection()
        if not selected:
            return
        index = selected[0]
        if index < len(self.operations) - 1:
            self.operations[index], self.operations[index + 1] = self.operations[index + 1], self.operations[index]
            self.update_operations_list()
            self.operations_list.select_set(index + 1)

    def remove_operation(self):
        selected = self.operations_list.curselection()
        if not selected:
            return
        index = selected[0]
        del self.operations[index]
        self.update_operations_list()

    def configure_paths(self):
        """配置程序路径对话框"""
        dialog = Toplevel(self.root)
        dialog.title("配置程序路径")
        dialog.geometry("500x300")
        dialog.transient(self.root)
        dialog.grab_set()

        # 对话框内容
        content_frame = ttk.Frame(dialog)
        content_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 当前配置显示
        ttk.Label(content_frame, text="当前程序路径配置:").pack(anchor=tk.W, pady=5)

        config_text = ScrolledText(content_frame, height=8, wrap=tk.WORD)
        config_text.pack(fill=tk.BOTH, expand=True, pady=5)

        # 显示当前配置
        config_text.insert(tk.END, "产品名称\t程序路径\n")
        config_text.insert(tk.END, "-" * 50 + "\n")
        for product, path in self.product_paths.items():
            config_text.insert(tk.END, f"{product}\t{path}\n")
        config_text.config(state=tk.DISABLED)

        # 添加新配置
        def add_new_config():
            product = simpledialog.askstring("添加配置", "请输入产品名称:")
            if not product:
                return

            path = filedialog.askopenfilename(
                title=f"选择 {product} 程序路径",
                filetypes=[("可执行文件", "*.exe"), ("所有文件", "*.*")]
            )

            if path:
                self.product_paths[product] = path
                messagebox.showinfo("成功", f"已添加 {product} 的路径配置")
                dialog.destroy()
                self.configure_paths()  # 重新打开以刷新显示

        btn_frame = ttk.Frame(dialog)
        btn_frame.pack(fill=tk.X, padx=10, pady=10)

        ttk.Button(btn_frame, text="添加新配置", command=add_new_config).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="关闭", command=dialog.destroy).pack(side=tk.RIGHT, padx=5)

    def run_operations(self):
        if not self.data:
            messagebox.showwarning("无数据", "请先导入数据")
            return

        if not self.operations:
            messagebox.showwarning("无操作", "请添加至少一个操作")
            return

        # 确认执行
        if not messagebox.askyesno(
                "确认执行",
                f"即将对 {len(self.data)} 条数据执行 {len(self.operations)} 个操作。\n请确保程序窗口处于活动状态。"
        ):
            return

        # 执行操作
        self.status_var.set("正在执行操作...")
        self.root.update()  # 更新UI

        # 创建截图保存目录
        screenshot_dir = "screenshots"
        os.makedirs(screenshot_dir, exist_ok=True)

        for idx, item in enumerate(self.data):
            self.status_var.set(f"处理 {item['filename']} ({idx + 1}/{len(self.data)})")
            self.root.update()

            for op in self.operations:
                try:
                    if op["type"] == "open_app":
                        self.open_application(item["product"])
                    elif op["type"] == "change_language":
                        self.change_language(item["language"])
                    elif op["type"] == "screenshot":
                        self.take_screenshot(item["filename"], screenshot_dir)

                    # 操作间延时
                    time.sleep(1)
                except Exception as e:
                    messagebox.showwarning("操作错误", f"执行操作时出错: {str(e)}")
                    break

        self.status_var.set(f"完成! 已处理 {len(self.data)} 条数据")
        messagebox.showinfo("完成", f"所有操作已执行完成!\n截图保存在: {os.path.abspath(screenshot_dir)}")

    def open_application(self, product_name):
        """打开指定应用程序"""
        if product_name in self.product_paths:
            os.startfile(self.product_paths[product_name])
            time.sleep(3)  # 等待程序启动
        else:
            raise Exception(f"未找到产品 '{product_name}' 的路径配置")

    def change_language(self, target_language):
        """切换程序语言到指定语言"""
        # 语言映射
        language_positions = {
            "it": ("Italiano", 1),
            "de": ("Deutsch", 2),
            "fr": ("Français", 3),
            "pt": ("Português", 4),
            "pl": ("Polski", 5),
            "es": ("Español", 6),
            "jp": ("日本語", 7),
            "kr": ("한국어", 8),
            "zh": ("中文简体", 9),
            "tw": ("中文繁體", 10)
        }

        # 获取目标语言的位置
        if target_language not in language_positions:
            raise Exception(f"不支持的语言: {target_language}")

        lang_name, position = language_positions[target_language]

        # 模拟鼠标操作
        pyautogui.moveTo(1340, 233, duration=0.5)  # 移动到语言下拉框
        pyautogui.click()
        time.sleep(0.5)

        pyautogui.moveTo(1221, 286, duration=0.5)  # 展开下拉框
        pyautogui.click()
        time.sleep(0.5)

        pyautogui.moveTo(1360, 290, duration=0.5)  # 移动到英语位置

        # 向下移动到目标语言位置
        pyautogui.move(0, 30 * position, duration=0.5)
        pyautogui.click()
        time.sleep(1)

    def take_screenshot(self, filename, save_dir):
        """截取程序窗口并保存为指定文件名"""
        # 截图区域 (448,206) 到 (1475,870)
        region = (448, 206, 1027, 664)  # 宽度: 1475-448=1027, 高度: 870-206=664
        screenshot = pyautogui.screenshot(region=region)

        # 保存截图
        save_path = os.path.join(save_dir, filename)
        screenshot.save(save_path)
        time.sleep(0.5)


if __name__ == "__main__":
    root = tk.Tk()
    app = AutomationApp(root)
    root.mainloop()